#include "StaticText.h"
#include "Stream.h"

#include "zlib.h"
#include "LightAbstractRenderer.h"
#include "TagList.h"
#include "CharacterList.h"
#include "Shape.h"

namespace LightPlayer{


	void GLYPHENTRY::readFromStream( Stream* stream, const TAG& actual_tag, int GlyphBits, int AdvanceBits ){
		init();

		m_GlyphIndex = stream->read_uint(GlyphBits);
		m_XAdvance = TWIPS_TO_PIXELS( stream->read_sint(AdvanceBits) );
	}



	void TEXTRECORD::init(){
		m_FontId = 0;
		m_pFont = NULL;
		m_ColorTransform.init();
		m_Transform.setIdentity();
		m_TextHeight = 0;
		m_Glyphs.clear();
	}

	bool TEXTRECORD::readFromStream( Stream* stream, const TAG& actual_tag, CharacterList* pCharacterList /*= NULL */, int GlyphBits, int AdvanceBits, TEXTRECORD_StateInfo& StateInfo/* = TEXTRECORD_StateInfo()*/ )
	{
		init();

		stream->align();

		int text_record_type = stream->read_uint(1);
		int style_flag_reserved = stream->read_uint(3);
		bool has_font = stream->read_bool();
		bool has_color = stream->read_bool();
		bool has_Y_offset = stream->read_bool();
		bool has_X_offset = stream->read_bool();

		if( !has_font && !has_color && !has_Y_offset && !has_X_offset && text_record_type == 0 &&  style_flag_reserved == 0 ){
			return false; // return false if the TEXTRECORD is EndOdRecordsFlag  ( first 8 bits are set to 0 )
		}

		// Font Read
		if(has_font){
			StateInfo.FontId = stream->read_u16();
		}
		m_FontId = StateInfo.FontId;
		if(pCharacterList){ // resolve Font* dependencie 
			m_pFont = pCharacterList->getFont( m_FontId );
		}

		// Color Read
		if(has_color){
			if(actual_tag.type == eDefineText2){
				StateInfo.Color.readFromStream(stream);
			}
			else{
				StateInfo.Color.readRGBFromStream(stream);
			}
		}
		m_ColorTransform._MultR = StateInfo.Color.R01();
		m_ColorTransform._MultG = StateInfo.Color.G01();
		m_ColorTransform._MultB = StateInfo.Color.B01();
		m_ColorTransform._MultA = StateInfo.Color.A01();


		// X read
		if(has_X_offset){
			StateInfo.XOffset = TWIPS_TO_PIXELS(stream->read_s16());
		}
		m_Transform.setX( StateInfo.XOffset );

		// Y Read
		if(has_Y_offset){
			StateInfo.YOffset = TWIPS_TO_PIXELS(stream->read_s16());
		}
		m_Transform.setY( StateInfo.YOffset );


		// font size read
		if(has_font){
			StateInfo.FontSize =  (uint16) TWIPS_TO_PIXELS( stream->read_u16() );
		}
		m_TextHeight = StateInfo.FontSize;


		uint8 glyph_count = stream->read_u8();
		m_Glyphs.resize(glyph_count);
		for (uint16 i=0; i<glyph_count; ++i){
			m_Glyphs[i].readFromStream( stream, actual_tag, GlyphBits, AdvanceBits );
			StateInfo.XOffset += m_Glyphs[i].getAdvance();
		}

		stream->align();

		return true;
	}

	void TEXTRECORD::draw( LightAbstractRenderer* pRenderer, SceneObject* pInstance )
	{
		if( !m_pFont ){
			assert(0); // font missing, cannot draw
			return;
		}
		pRenderer->pushMatrix( m_Transform );
		pRenderer->pushCXFORM( m_ColorTransform );

		MATRIX glyph_transform;
		float glyph_scale = m_TextHeight / (1024.0f/20.0f);
		glyph_transform.setScaleMatrix( glyph_scale, glyph_scale );

		int glyph_count = m_Glyphs.size();
		for (int i=0; i < glyph_count; ++i ){
			Shape* glyph = m_pFont->getGlyph( m_Glyphs[i].getIndex() );
			if(glyph){
				pRenderer->pushMatrix( glyph_transform );

				glyph->draw( pRenderer, pInstance );

				pRenderer->popMatrix();
			}
			glyph_transform.setX( glyph_transform.getX() + m_Glyphs[i].getAdvance() );
		}

		pRenderer->popCXFORM();
		pRenderer->popMatrix();
	}




	void StaticText::init(){
		m_CharacterId = 0;
		m_TextBounds.init();
		m_Transformation.setIdentity();
		m_TextRecordList.clear();
	}

	void StaticText::readFromStream( Stream* stream, const TAG& actual_tag, CharacterList* pCharacterList /*= NULL*/ ){
		init();

		m_TextBounds.readFromStream( stream );
		m_Transformation.readFromStream( stream );

		int GlyphBits = stream->read_u8();
		int AdvanceBits = stream->read_u8();

		TEXTRECORD_StateInfo StateInfo;

		m_TextRecordList.reserve(20);
		//
		do{
			m_TextRecordList.resize( m_TextRecordList.size() + 1 );
		}while( m_TextRecordList.back().readFromStream( stream, actual_tag, pCharacterList, GlyphBits, AdvanceBits, StateInfo ) );
		//
		m_TextRecordList.pop_back(); // remove EndOdRecordsFlag
		m_TextRecordList.shrink_to_fit();
	}

	void StaticText::draw( LightAbstractRenderer* pRenderer, SceneObject* pInstance )
	{
		pRenderer->pushMatrix( m_Transformation );

		int text_record_count = m_TextRecordList.size();
		for (int i=0; i < text_record_count; ++i ){
			m_TextRecordList[i].draw( pRenderer, pInstance );
		}

		pRenderer->popMatrix();
	}

};